package wit.p2a;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.CompoundButton.OnCheckedChangeListener;

import at.abraxas.amarino.Amarino;
import at.abraxas.amarino.AmarinoIntent;

public class P2AStart extends Activity {
	/** Called when the activity is first created. */
	
	// change this to your Bluetooth device address 
	private static final String DEVICE_ADDRESS =  "00:13:EF:00:00:2F"; //"00:06:66:03:73:7B";
	
	private ArduinoReceiver arduinoReceiver = new ArduinoReceiver();
	private Communication comm;
	private TextView textMessage;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		TextView ipView  = (TextView)findViewById(R.id.textOwnIp);
		// Show own WLAN address
		ipView.setText(getWifiIpAddress());
		textMessage = (TextView)findViewById(R.id.MessageText);
		comm = new Communication();
		comm.execute(getWifiIpAddress());
		
        Button button = (Button) findViewById(R.id.btnConnect);
        button.setOnClickListener(new OnClickListener() {
			//@Override
			public void onClick(View arg0) {
				try {
					EditText answerEditText = (EditText)findViewById(R.id.EditTextAnswer);
					String answer = answerEditText.getText().toString();
					if (comm.isListening && answer.length()>0)
						comm.sendLine(answer);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}				
			}
        });
        
        CheckBox checkBox = (CheckBox) findViewById(R.id.CheckBoxArduinoLED);
        checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			//@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				if (isChecked)
					Amarino.sendDataToArduino(getBaseContext(), DEVICE_ADDRESS, 'T', 1);
				else
					Amarino.sendDataToArduino(getBaseContext(), DEVICE_ADDRESS, 'T', 0);
			}
        });
	}

	@Override
	protected void onStart() {
		super.onStart();
		// in order to receive broadcasted intents we need to register our receiver
		registerReceiver(arduinoReceiver, new IntentFilter(AmarinoIntent.ACTION_RECEIVED));
		
		// this is how you tell Amarino to connect to a specific BT device from within your own code
		Amarino.connect(this, DEVICE_ADDRESS);
	}


	@Override
	protected void onStop() {
		super.onStop();
		
		// if you connect in onStart() you must not forget to disconnect when your app is closed
		Amarino.disconnect(this, DEVICE_ADDRESS);
		
		// do never forget to unregister a registered receiver
		unregisterReceiver(arduinoReceiver);
	}
	

	String getWifiIpAddress(){
		WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
		WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 
		if (wifiInfo == null){
			return "Wifi not connected";
		}
		return intToIp(wifiInfo.getIpAddress());
	}

	private String intToIp(int i) {
		return ( i        & 0xFF) + "." +
		((i >>  8 ) & 0xFF) + "." +
		((i >> 16 ) & 0xFF) + "." +
		((i >> 24 ) & 0xFF)
		;
	}

	private class Communication extends AsyncTask<String, String, String> {
		private ServerSocket mSocket;
		private int port = 40001;
		private Socket mConnection;
		private BufferedReader mInputReader;
		private BufferedWriter mOutputWriter;
		public boolean isListening = false;

		public void sendLine(String data) throws IOException{
			mOutputWriter.write(data + "\n");
			mOutputWriter.flush();
		}

		protected void onProgressUpdate(String... progress) {
			textMessage.setText(progress[0]);
		}

		protected void onPostExecute(String result) {
		}

		@Override
		protected String doInBackground(String... params) {
			InetSocketAddress address;
			String line;
			try {
				mSocket = new ServerSocket();
				address = new InetSocketAddress(params[0], port);
				mSocket.bind(address);
				mConnection = mSocket.accept();
				mInputReader = new BufferedReader(new InputStreamReader(mConnection.getInputStream()));
				mOutputWriter = new BufferedWriter(new OutputStreamWriter(mConnection.getOutputStream()));
				isListening = true;
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				while (!isCancelled()){
//					if (!mConnection.isBound()){
//						mConnection = mSocket.accept();
//						mInputReader = new BufferedReader(new InputStreamReader(mConnection.getInputStream()));
//						mOutputWriter = new BufferedWriter(new OutputStreamWriter(mConnection.getOutputStream()));
//						isListening = true;
//					}
					line = mInputReader.readLine();
					while (line != null){
						Amarino.sendDataToArduino(getBaseContext(), DEVICE_ADDRESS, 'A', line);
						publishProgress(line);
						//sendLine("echo:"+line);
						line = mInputReader.readLine();
					}
					Thread.sleep(50);
				}
				if (mConnection.isConnected()){
					mConnection.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			} catch (InterruptedException e) {
				e.printStackTrace();
				return null;
			}
			return null;
		}
	}


	/**
	 * ArduinoReceiver is responsible for catching broadcasted Amarino
	 * events.
	 * 
	 * It extracts data from the intent and updates the graph accordingly.
	 */
	public class ArduinoReceiver extends BroadcastReceiver {

		public void onReceive(Context context, Intent intent) {
			String data = null;

			// the device address from which the data was sent, we don't need it here but to demonstrate how you retrieve it
			final String address = intent.getStringExtra(AmarinoIntent.EXTRA_DEVICE_ADDRESS);

			// the type of data which is added to the intent
			final int dataType = intent.getIntExtra(AmarinoIntent.EXTRA_DATA_TYPE, -1);

			// we only expect String data though, but it is better to check if really string was sent
			// later Amarino will support differnt data types, so far data comes always as string and
			// you have to parse the data to the type you have sent from Arduino, like it is shown below
			if (dataType == AmarinoIntent.STRING_EXTRA){
				data = intent.getStringExtra(AmarinoIntent.EXTRA_DATA);

				if (data != null){
					//mValueTV.setText(data);
					try {
						comm.sendLine("echo:"+data);
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					try {
						// since we know that our string value is an int number we can parse it to an integer
						final int sensorReading = Integer.parseInt(data);
						//mGraph.addDataPoint(sensorReading);
					} 
					catch (NumberFormatException e) { /* oh data was not an integer */ }
				}
			}
		}
	}

}
